Skip to content

docs: port missing best-practices content from portal#246

Draft
marc0olo wants to merge 7 commits into
mainfrom
docs/best-practices-gaps
Draft

docs: port missing best-practices content from portal#246
marc0olo wants to merge 7 commits into
mainfrom
docs/best-practices-gaps

Conversation

@marc0olo
Copy link
Copy Markdown
Member

Closes #241

Summary

  • Gap 1 (small): Added canister-per-user architectural pattern to concepts/app-architecture.md, including the honest note that no successful end-to-end implementation exists yet and the correction of the scalability misconception (per-subnet is more performant than per-user)
  • Gap 2 (medium): New guides/canister-management/trust-in-canisters.md — cohesive user-facing trust assessment guide: two-question framework, Wasm hash verification, canister history tracking, controller verification via icp canister status, trust spectrum table (developer-controlled → multi-sig → SNS → black-holed), black hole canister details, and caveat for self-reinstalling canisters
  • Gap 3 (medium): Extended guides/backends/data-persistence.mdx with a "Storage recommendations" section: heap-vs-stable decision table, mo:core data structure guidance (Map, List, Queue, pure/Map, pure/Set), Rust cautions on Vec/String serialization, state backup strategies, transaction history patterns
  • Gap 4 (small): New guides/canister-calls/pagination.md — cursor-based pagination for mutable datasets, with Motoko and Rust examples, handling deleted cursors, and sort order stability notes
  • Gap 5 (large): New guides/canister-management/troubleshooting.md — fully rewritten for icp CLI; covers network latency, subnet load identification, compute allocation, boundary node info for support escalation, heap-vs-stable latency, inter-canister call optimization, frontend CSP violations, .ic-assets.json5 security policy warnings, and Rust Wasm import errors. All dfx-era content (cycles wallet, dfxvm, WSL) excluded.
  • Cross-links added from reproducible-builds.md and canister-control.md to the new trust guide

Sync recommendation

informed by dfinity/portal — docs/building-apps/best-practices/application-architectures.mdx, trust-in-canisters.mdx, storage.mdx, general.mdx (pagination item), troubleshooting.mdx

Five gaps ported from dfinity/portal building-apps/best-practices/:

- Extend app-architecture.md with canister-per-user pattern including
  the honest note that no successful end-to-end implementation exists yet
  and the misconception correction (per-subnet is more scalable)
- New trust-in-canisters.md guide: two-question trust framework, Wasm
  hash verification, canister history, controller verification, trust
  spectrum (developer to multi-sig to SNS to black-holed), black hole
  canister caveat for self-reinstalling code
- Extend data-persistence.mdx: Storage recommendations section with
  heap-vs-stable decision table, mo:core data structure guidance,
  Rust cautions, state backup, transaction history patterns
- New pagination.md guide: cursor-based pagination for mutable datasets,
  handling deleted cursors, sort order stability
- New troubleshooting.md guide: rewritten for icp CLI; latency diagnosis,
  compute allocation, CSP fix, Wasm import errors; dfx-era content excluded
- Cross-links added in reproducible-builds.md and canister-control.md
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 12, 2026

🤖 Here's your preview: https://keluh-vqaaa-aaaam-ai7wa-cai.icp0.io

- Fix Map.entries() call in pagination.md Motoko example (no comparator arg)
- Remove unused import Iter in pagination.md
- Add sidebar orders to pagination.md (6), idempotency.md (5),
  trust-in-canisters.md (11), troubleshooting.md (12); orders 11-12
  leave room for canister-migration.md (10) from PR #245
- Add subnet migration subsection to troubleshooting.md latency problem
- Fix icp canister status flag: -n ic -> -e ic in trust-in-canisters.md
- Link SNS term in trust spectrum table to concepts/sns-framework.md
- Add pagination.md to inter-canister-calls.mdx Next steps
@marc0olo
Copy link
Copy Markdown
Member Author

Review fixes applied:

  • Fixed Map.entries(items, Nat.compare)Map.entries(items) in pagination.md Motoko example (wrong signature — no comparator arg)
  • Removed unused import Iter "mo:core/Iter" in pagination.md
  • Added sidebar.order to all three new pages and to pre-existing idempotency.md; orders 11–12 leave slot 10 free for canister-migration.md from PR docs(canister-management): add canister migration guide, improve subnet selection, reorder sidebar #245
  • Added "Consider migrating to a less-loaded subnet" subsection to troubleshooting.md latency problem (was in portal source, was missing)
  • Fixed icp canister status flag: -n ic-e ic in trust-in-canisters.md
  • Linked "SNS (Service Nervous System)" in trust spectrum table to concepts/sns-framework.md
  • Added pagination.md to inter-canister-calls.mdx Next steps

Merge dependency on #245: Merge #245 first. Before merging this PR, update troubleshooting.md line 46: change subnet-selection.md#canister-is-on-the-wrong-subnetcanister-migration.md now that the dedicated migration guide will exist.

marc0olo added 4 commits May 12, 2026 16:32
Validation script requires hand-written, sync from, or informed by.
Changed "ported from" and "rewritten (not ported) from" to "informed by"
in pagination.md, trust-in-canisters.md, and troubleshooting.md.
- Motoko: Array.append does not exist in mo:core/Array; replace with Array.concat
- Rust: Item struct used as StableBTreeMap value requires Storable impl; add it
  using ciborium CBOR serialization, consistent with stable-structures.md pattern
@marc0olo
Copy link
Copy Markdown
Member Author

Review fixes applied (second round — code correctness):

  • Motoko bug: Array.append does not exist in mo:core/Array. The correct function is Array.concat. Fixed in pagination.md line 57.
  • Rust bug: Item struct used as the value type in StableBTreeMap<u64, Item, Memory> was missing a Storable implementation. StableBTreeMap requires both key and value types to implement Storable; u64 implements it already but custom structs do not. Added impl Storable for Item using ciborium CBOR serialization, consistent with the pattern in languages/rust/stable-structures.md. Also added Serialize to the derives and the necessary imports (ic_stable_structures::storable::{Bound, Storable}, serde::Serialize, std::borrow::Cow).

Spawning a user canister carries the same overhead as a fresh canister
install. This was in the portal storage.mdx efficiency recommendations
but belongs here alongside the other canister-per-user caveats.
@marc0olo
Copy link
Copy Markdown
Member Author

Review fix applied (portal gap — actor class instantiation cost):

Added a bullet to the canister-per-user "Things to know" list in concepts/app-architecture.md:

Spawning a user canister (via an actor class in Motoko or a management canister create_canister call in Rust) carries the same cost as a fresh canister install. Do it once per user at account creation, never on a hot call path.

Source: .sources/portal/docs/building-apps/best-practices/storage.mdx line 55 — this was in the portal's Motoko efficiency list alongside the data-structure recommendations that were ported to data-persistence.mdx. It belongs on the architecture page because the warning is most actionable when a developer is deciding to use the canister-per-user pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: port missing best-practices content from portal

1 participant